#include "EventLoop.h"
#include "Poller.h"
#include "TimerId.h"
#include "Channel.h"
// #include <muduo/base/Logging.h>
#include <sys/poll.h>
#include <sys/eventfd.h>
#include <cassert>

// __thread EventLoop* t_loopInThisThread = 0;
thread_local EventLoop* t_loopInThisThread = nullptr; // c++11
const int kPollTimeMs = 10000;

int createEventfd()
{
    int evtfd = ::eventfd(0,  EFD_NONBLOCK | EFD_CLOEXEC);
    if(evtfd < 0)
    {
        perror("::eventfd");
        abort();
    }
    return evtfd;
}

EventLoop::EventLoop()
: _isLooping(false)
, _quit(false)
, _callingPendingFunctors(false)
, _threadId(CurrentThread::tid())
, _poller(std::make_unique<Poller>(this))
, _timerQueue(std::make_unique<TimerQueue>(this))
, _wakeupFd(createEventfd())
, _wakeupChannel(std::make_unique<Channel>(this, _wakeupFd))
, _activeChannels()
, _mutex()
, _pendingFunctors()
{
    // LOG_TRACE << "EventLoop created " << this << " in thread" << _threadId;
    cout << "EventLoop created " << this << " in thread" << _threadId << "\n";
    if(t_loopInThisThread)
    {
        // LOG_FATAL << "already have EventLoop " 
        // << t_loopInThisThread << " in this thread " << _threadId <<".";
        std::cerr << "FATAL: already have EventLoop "
                  << t_loopInThisThread << " in thread "
                  << _threadId << std::endl;
        std::exit(EXIT_FAILURE);
    }
    else
    {
        cout << "thread " <<  _threadId << " bind EventLoop " << this << "\n";
        t_loopInThisThread = this; // 记录loop到当前thread
    }
}
EventLoop::~EventLoop()
{
    assert(!_isLooping);
    t_loopInThisThread = NULL;
}

EventLoop *EventLoop::getEventLoopOfCurrentThread()
{
    return t_loopInThisThread;
}

void EventLoop::loop()
{
    assert(!_isLooping);
    assertInLoopThread();
    _isLooping;

    // ::poll(NULL, 0, 5000); // wait 5s exit
    // LOG_TRACE << "EventLoop " << this << " stop looping.";
    while(!_quit)
    {
        _activeChannels.clear();
        _pollReturnTime = _poller->poll(kPollTimeMs, &_activeChannels);
        for(auto it = _activeChannels.begin(); it != _activeChannels.end(); ++it)
        {
            (*it)->handleEvent(_pollReturnTime);
        }
        doPendingFunctors(); //执行跨线程回调
    }
    cout << "EventLoop " << this << " stop looping.\n";
    _isLooping = false;
}

void EventLoop::abortNotInLoopThread()
{
    std::cerr << "EventLoop::abortNotInLoopThread - EventLoop " << this
              << " was created in threadId_ = " << _threadId
              << ", current thread id = " << CurrentThread::tid() << "\n";
    std::exit(EXIT_FAILURE);
}

void EventLoop::quit()
{
    _quit = false;
    if(!isInLoopThread()) //唤醒IO线程 及时终止事件循环
    {
        wakeup();
    }
}

void EventLoop::updateChannel(Channel *channel)
{
    assert(channel->ownerLoop() == this);
    assertInLoopThread();
    _poller->updateChannel(channel); //交给poller更新
}

void EventLoop::removeChannel(Channel *channel)
{
    assert(channel->ownerLoop() == this);
    assertInLoopThread();
    _poller->removeChannel(channel); //交给poller删除
}
TimerId EventLoop::runAt(Timestamp time, EventLoop::TimerCallback cb)
{
    return _timerQueue->addTimer(std::move(cb), time, 0.0);
}
TimerId EventLoop::runAfter(double delay, EventLoop::TimerCallback cb)
{
    Timestamp time(addTime(Timestamp::now(), delay));
    return runAt(time, std::move(cb));
}
TimerId EventLoop::runEvery(double interval, EventLoop::TimerCallback cb)
{
    Timestamp time(addTime(Timestamp::now(), interval));
    return _timerQueue->addTimer(std::move(cb), time, interval);
}

void EventLoop::runInLoop(EventLoop::Functor cb)
{
    if(isInLoopThread())
    {
        cb();
    }
    else
    {
        queueInLoop(std::move(cb));
    }
}

void EventLoop::queueInLoop(Functor cb)
{
    {
        std::lock_guard lock(_mutex);
        _pendingFunctors.push_back(cb); //先存入
    }    
    if(!isInLoopThread() || _callingPendingFunctors)
    {
        wakeup();
    }
}
void EventLoop::wakeup()
{
    uint64_t one = 1;
    ssize_t n = ::write(_wakeupFd, &one, sizeof one);
    if(n != sizeof one)
    {
        std::cerr << "EventLoop::wakeup() writes " << n << " bytes instead of 8\n";
    }
}

void EventLoop::handleRead()
{
    uint64_t one = 1;
    ssize_t n = ::read(_wakeupFd, &one, sizeof one);
    if(n != sizeof one)
    {
        std::cerr << "EventLoop::handleRead() reads " << n << " bytes instead of 8\n";
    }
}
void EventLoop::doPendingFunctors()
{
    vector<Functor> functors; //减少临界区长度 避免死锁
    _callingPendingFunctors = true;
    {
        std::lock_guard lock(_mutex);
        functors.swap(_pendingFunctors);//全部取出 
    }//释放锁:意味着不会再阻塞其他IO线程调用queueInLoop()
    for(const Functor &func : functors)
    {
        func(); // 可能再次跨线程调用 queueInLoop(cb)需要直接唤醒线程 
    }
    _callingPendingFunctors = false;
}